/* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */
/* Copyright (C) 2012 Zongyou Yao. All rights reserved.     */

#ifndef STR_INCLUDED
#define STR_INCLUDED

#include <stdarg.h>
#include "fmt.h"

/**
 * The str functions manipulate null-terminated strings. Positions identify points
 * between characters; for example, the positions in STRING are:
 *                     1  2  3  4  5  6 7
 *                      S  T  R  I  N  G
 *                    -6 -5 -4 -3 -2 -1 0
 * Any two positions can be given in either order. str functions that create strings
 * allocate space for their results. In the descriptions below, s[i:j] denotes the 
 * substring of s between positions i and j. It is a checked runtime error to pass
 * a nonexistent position or a null character pointer to any str function, except
 * as specified for str_catv and str_map.
 */

/**
 * Returns s[i:j].
 * Exception mem_failed can be raised.
 */
char *str_sub(const char *s, int i, int j);

/**
 * Returns n copies of s[i:j]. It is a checked runtime error for n < 0.
 * Exception mem_failed can be raised.
 */
char *str_dup(const char *s, int i, int j, int n);

/**
 * Returns s1[i1:j1] concatenated with s2[i2:j2].
 * Exception mem_failed can be raised.
 */
char *str_cat(const char *s1, int i1, int j1, const char *s2, int i2, int j2);

/**
 * Returns a string consisted of the triples in "..." up to a null pointer.
 * Each triple specifies an s[i:j].
 * Exception mem_failed can be raised.
 */
char *str_catv(const char *s, ...);

/**
 * Returns a copy of s[i:j] with the characters in the opposite order.
 * Exception mem_failed can be raised.
 */
char *str_reverse(const char *s, int i, int j);

/**
 * Returns the string obtained from mapping the characters in s[i:j] according
 * to from and to. Each character from s[i:j] that appears in from is mapped to
 * the corresponding character in to. Characters that do not appear in from map 
 * to themselves. If from == null and to == null, their previous values are used.
 * If s == null, from and to establish a default mapping. It is a checked runtime
 * error for only one of from or to to be null, for strlen(from) != strlen(to), 
 * for s, from, and to to all be null, or for from == null and to == null on the 
 * first call.
 * Exception mem_failed can be raised.
 */
char *str_map(const char *s, int i, int j, const char *from, const char *to);

/**
 * Returns the positive position corresponding to s[i:i]; subtracting one yields
 * the index of s[i:i+1].
 */
int str_pos(const char *s, int i);

/**
 * Returns the length of s[i:j].
 */
int str_len(const char *s, int i, int j);

/**
 * Returns an integer < 0, = 0, or > 0 if s1[i1:j1] < s2[i2:j2], 
 * s1[i1:j1] = s2[i2:j2], or s1[i1:j1] > s2[i2:j2].
 */
int str_cmp(const char *s1, int i1, int j1, const char *s2, int i2, int j2);

/**
 * Returns the position in s before the leftmost occurrence of c in s[i:j], or 
 * zero otherwise.
 */
int str_chr(const char *s, int i, int j, int c);

/**
 * Is the rightmost variant of str_chr.
 */
int str_rchr(const char *s, int i, int j, int c);

/**
 * Returns the position in s before the leftmost occurrence in s[i:j] of any
 * character in set, or zero otherwise. It is a checked runtime error for set == null.
 */
int str_upto(const char *s, int i, int j, const char *set);

/**
 * Is the rightmost variant of str_upto.
 */
int str_rupto(const char *s, int i, int j, const char *set);

/**
 * Returns the position in s before the leftmost occurrence of str in s[i:j], 
 * or zero otherwise. It is a checked runtime error for str == null.
 */
int str_find(const char *s, int i, int j, const char *str);

/**
 * Is the rightmost variant of str_find.
 */
int str_rfind(const char *s, int i, int j, const char *str);

/**
 * Returns the positive position in s after s[i:i+1] if that character appears
 * in set, or zero otherwise. It is a checked runtime error for set == null.
 */
int str_any(const char *s, int i, const char *set);

/**
 * Returns the positive position in s after a nonempty run of characters from set
 * at the beginning of s[i:j], or zero otherwise. It is a checked runtime error 
 * for set == null.
 */
int str_many(const char *s, int i, int j, const char *set);

/**
 * Returns the positive position in s before a nonempty run of characters from 
 * set at the end of s[i:j], or zero otherwise. It is a checked runtime error 
 * for set == null.
 */
int str_rmany(const char *s, int i, int j, const char *set);

/**
 * Returns the positive position in s if s[i:j] starts with str, or zero otherwise.
 * It is a checked runtime error for str == null.
 */
int str_match(const char *s, int i, int j, const char *str);

/**
 * Returns the positive position in s before str if s[i:j] ends with str, or zeor
 * otherwise. It is a checked runtime error for str == null.
 */
int str_rmatch(const char *s, int i, int j, const char *str);

/**
 * Is a fmt conversion function. It consumes three arguments -- a string and two
 * positions -- and formats the substring in the style of printf's %s. It is a
 * checked runtime error for app or flags to be null.
 */
void str_fmt(int code, va_list_box *box, int put(int c, void *cl), void *cl, unsigned char flags[], int width, int precision);

#endif
